package com.me.supermario.entities;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.maps.tiled.TiledMapTileLayer;
import com.badlogic.gdx.maps.tiled.TiledMapTileLayer.Cell;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;

public abstract class Funghi extends Sprite {
	//IMPORTANTI
		private Vector2 velocity = new Vector2 ();
		private TiledMapTileLayer collisionLayer;
		protected Rectangle rect = new Rectangle ();
		protected static Sprite sprite = new Sprite( new Texture("com/me/img/fungosheet.png"));
		
		//VARIABILI FLOAT
		private float speed = 30 * 2, gravity = 200 * 1.8f, increment;
		private float oldSpeed;
		
		//VARIABILI BOOLEANE
		private boolean firstTime = true;	
		private boolean deadState;
		
		//STRINGHE E PROPRIETA' DEI TILE
		private String blockedKey = "blocked";
		private String mushBlockedKey = "blocked";

		//COSTRUTTORE
		public Funghi (TiledMapTileLayer collisionLayer) {
			super(sprite);
			this.collisionLayer = collisionLayer;
		}//costruttore
	 
		public void draw (SpriteBatch spritebatch) {
			update(Gdx.graphics.getDeltaTime());
			super.draw(spritebatch);
		}//draw

		private void update(float delta) {
			//System.out.println ("entro in update");
			velocity.y -= gravity*delta;
			
			if (firstTime){
				//System.out.println ("entro in firsttime");
				velocity.x = -speed;
				firstTime=false;
			} else {velocity.x = oldSpeed; //System.out.println ("OldSPeed = " + oldSpeed);}
			}
			//System.out.println ("Velocita' = " + velocity.x);
			//System.out.println (firstTime);
			
			
			if(velocity.y > speed)
				velocity.y = speed; //la velocita' non puo' andare oltre a speed
			else if(velocity.y < -speed)
				velocity.y = -speed;
			
			//salva le vecchie posizioni
			//float oldX = getX();
			float oldY = getY();
			//settiamo due valori booleani: uno per vedere se collidiamo nell'asse X, uno per l'asse Y
			//boolean collisionX = false;
			boolean collisionY = false;

			// muovi in x
			setX(getX() + velocity.x * delta);

			// calculate the increment for step in #collidesLeft() and #collidesRight()
			increment = collisionLayer.getTileWidth();
			increment = getWidth() < increment ? getWidth() / 2 : increment / 2;

			// muovi in Y
			setY(getY() + velocity.y * delta * 5f);

			// calculate the increment for step in #collidesBottom() and #collidesTop()
			increment = collisionLayer.getTileHeight();
			increment = getHeight() < increment ? getHeight() / 2 : increment / 2;

			if(velocity.y < 0){ // stai andando giu'
				collisionY = collidesBottom();

			}
			else if(velocity.y > 0) // stai andando su
				collisionY = collidesTop();

			// gestisci la collisione in Y
			if(collisionY) {
				setY(oldY);
				velocity.y = 0;
			}
			
	//------------------------
			
			boolean pathX = false;
			
			if(velocity.x < 0) // stai andando a sinistra
				pathX = collidesLeftTest();
			else if(velocity.x > 0) // stai andando a destra
				pathX = collidesRightTest();
			
			if (pathX){
				//setX(oldX - velocity.x*delta);
				//cambiadirezione
				//setX(oldX);
				if (velocity.x < 0){
				velocity.x = speed;
				this.oldSpeed = velocity.x;
				setX(getX() + velocity.x * delta);
				//System.out.println (velocity.x);
				}
				else if (velocity.x > 0){
					velocity.x = -speed;
					this.oldSpeed = velocity.x;
					setX(getX() + velocity.x * delta);
					//System.out.println (velocity.x);
					}
			}
			
			//aggiorna l'animazione
			//animationTime += delta;
			//setRegion(velocity.x < 0 ? still.getKeyFrame(animationTime) : velocity.x > 0 ? still.getKeyFrame(animationTime) : still.getKeyFrame(animationTime));
		
			this.oldSpeed = velocity.x;
			//System.out.println ("FINE: Velocita' = " + velocity.x);
			
		}//update
		
		protected Rectangle rectangle() {
			return new Rectangle(this.getX(), this.getY(), this.getWidth(), this.getHeight());
		}//rectangle
		
		public void deadByTrample() {
	        velocity.set(0, 0);
	        deadState = true;
		}//deadByTrample


		//METODI DI COLLISIONE
		private boolean isCellMushBlocked(float x, float y) {
			Cell cell = collisionLayer.getCell((int) (x / collisionLayer.getTileWidth()), (int) (y / collisionLayer.getTileHeight()));
			return cell != null && cell.getTile() != null && cell.getTile().getProperties().containsKey(mushBlockedKey);
		}//isCellMushBlocked
		
		private boolean isCellBlocked(float x, float y) {
			Cell cell = collisionLayer.getCell((int) (x / collisionLayer.getTileWidth()), (int) (y / collisionLayer.getTileHeight()));
			return cell != null && cell.getTile() != null && cell.getTile().getProperties().containsKey(blockedKey);
		}//isCellBlocked

		public boolean collidesRight() {
			for(float step = 0; step < getHeight(); step += increment)
				if(isCellBlocked(getX() + getWidth(), getY() + step))
					return true;
			return false;
		}//collidesRIght

		public boolean collidesLeft() {
			for(float step = 0; step < getHeight(); step += increment)
				if(isCellBlocked(getX(), getY() + step))
					return true;
			return false;
		}//collidesLeft

		public boolean collidesLeftTest() {
			for(float step = 0; step < getHeight(); step += increment)
				if(isCellMushBlocked(getX(), getY() + step))
					return true;
			return false;
		}//collidesLeftTest
		
		public boolean collidesRightTest() {
			for(float step = 0; step < getHeight(); step += increment)
				if(isCellMushBlocked(getX() + getWidth(), getY() + step))
					return true;
			return false;
		}//collidesRightTest

		public boolean collidesTop() {
			for(float step = 0; step <getWidth(); step += increment)
				if(isCellBlocked(getX() + step, getY() + getHeight())){
					return true;
				}
			return false;
		}//collidesTop

		public boolean collidesBottom() {
			for(float step = 0; step < getWidth(); step += increment)
				if(isCellBlocked(getX() + step , getY() ))
					return true;
			return false;

		}//collidesBottom
		
		//METODI GETTERS
		public TiledMapTileLayer getCollisionLayer() {
			return collisionLayer;
		}//getCollisionLayer
		public boolean getDeadState() {
			return deadState;
		}//getDeadState
		
		protected void setSprite( Sprite newsprite ){
			this.sprite = newsprite;
		}
}
